Skip to content

Conversation

pamaury
Copy link

@pamaury pamaury commented Sep 10, 2025

Replaces #164. This creates a minimal implementation of the usbdev block. Currently, the only thing supported are interrupts and also VBUS handling through a dedicated chardev channel. This allows on to pass the usbdev_vbus_test (after some opentitantool changes). Since the usbdev driver will be quite complicated, I think it's better to start small and build up. I also plan to make it multi-file so I created a directory for it.

@pamaury pamaury changed the base branch from usbdev to ot-earlgrey-9.2.0 September 10, 2025 11:51
@pamaury pamaury force-pushed the usbdev branch 2 times, most recently from b3d7d26 to 49df0bb Compare September 10, 2025 12:48
Copy link

@rivos-eblot rivos-eblot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why we want to merge a full dummy device.
It seems for now it does nothing really useful(?)

What does this bring vs. the OT_UNIMP device it replaces?

@pamaury pamaury marked this pull request as draft September 10, 2025 13:16
@pamaury pamaury force-pushed the usbdev branch 3 times, most recently from 8048aee to 48bf161 Compare September 16, 2025 12:18
@pamaury pamaury changed the title [opentitan, usbdev] Create a dummy usbdev block [opentitan, usbdev] Create initial usbdev block Sep 30, 2025
@pamaury pamaury requested a review from rivos-eblot September 30, 2025 09:52
@pamaury pamaury force-pushed the usbdev branch 2 times, most recently from 6f5515e to 521a3c0 Compare September 30, 2025 09:56
@pamaury pamaury force-pushed the usbdev branch 3 times, most recently from 3d5a51b to 7c18b80 Compare October 6, 2025 08:41
@pamaury pamaury marked this pull request as ready for review October 6, 2025 08:44
@pamaury pamaury force-pushed the usbdev branch 3 times, most recently from 6e48879 to ed93075 Compare October 6, 2025 18:15
@rivos-eblot
Copy link

Note: it seems that PR title format should now be

`ot_usbdev`: Create initial usbdev block

looking at the recent PRs.

@pamaury pamaury force-pushed the usbdev branch 2 times, most recently from 517c204 to d1a35a7 Compare October 7, 2025 11:21
@pamaury pamaury changed the title [opentitan, usbdev] Create initial usbdev block ot_usbdev: Create initial usbdev block Oct 7, 2025
static void ot_usbdev_set_vbus_sense(OtUsbdevState *s, bool sense)
{
s->vbus_sense = sense;
/* @todo need to update the link state and trigger some events here */

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside: Maybe also trace here? This can be deferred until the actual implementation of the TODO though I think.

/* @todo cancel everything here. */

memset(s->regs, 0, sizeof(s->regs));
s->link_state = OT_USBDEV_LINK_STATE_DISCONNECTED;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming it is intentional, could you add a short comment here like

   /* s->vbus_sense should survive reset */

Copy link
Author

@pamaury pamaury Oct 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it's intentional, vbus sense is an external signal so there is not reason to reset it. That being said, VBUS handling will become a lot more complicated as we add more features so all of this code will chaneg anyway

memset(s->regs, 0, sizeof(s->regs));
s->link_state = OT_USBDEV_LINK_STATE_DISCONNECTED;

ot_usbdev_update_irqs(s);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably also ot_usbdev_update_alerts(s); here? Only alert test is implemented for now so it is not incorrect, but this would help prevent potential reset bugs when alerts are introduced to the USB device.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure why alerts would need to be updated here? Alerts are more like pulses: when you write a 1, the alert is fired but it's not a level interrupt, it's never left at level 1, and resetting the block does not trigger an alert either. I am missing something about alerts?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this is an issue with current QEMU alert modelling (which is already inconsistent). I think that currently we model fatal alerts as a level interrupt, perhaps that needs to be changed. For sticky (fatal) alerts, how does HW handle this? Does it send repeated pulses?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I discussed with Emmanuel and he said that alerts are not level interrupts because the alert handler does not clear them, and the IPs have no way of clearing it anyway. I followed what was done in the CSRNG driver of calling ibex_irq_set(&irq, 1) followed by ibex_irq_set(&irq, 0).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding (please correct me if incorrect) is that fatal alerts (unlike e.g. alert test which is transient, as your current code is) are treated as a level interrupt and stay asserted. In the alert handler, when an alert is handled, it should subsequently check if the alert is still asserted (i.e. fatal) and if so re-trigger the alert.

Maybe I'm misunderstanding and/or the alert handler in QEMU doesn't emulate this properly, but based on this understanding, fatal device alerts should stay high until reset, at which point we should ot_usbdev_update_alerts(s) to reset them back to 0?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is related to what I was trying to explain in another comment on the PR: my code will never throw a real alert (the only source of alerts in the RTL is a TL-UL integrity violation) so literally the only source of alert is the ALERT_TEST register.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On a related note: would it be better to have a different type for alerts and explicitely handle alert tests versus real alerts? Since this problem will happen in all drivers, it would be better to have generic infrastructure for that.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No sure to get it, sorry: different types where?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alerts are modelled as IbexIRQ, maybe we should have a IbexAlert?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok. Could be. IbexIRQ is only an optimization to avoid propagatin no-change again and again, but having an OtAlert type could help readibility. IbexIRQ is not OtIRQ as we were planning to use it for ibexdemo, but I do not think we made it.

@pamaury pamaury merged commit b28ee32 into lowRISC:ot-9.2.0 Oct 7, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants